// Copyright 2022 jeff.li. and/or its affiliates.

#pragma once

#include <string>

#include <tbir/runtime/unicodelib/unicode_ops.h>

namespace tbir::runtime {

    class String;

    class Unicode;

    static constexpr const short UTF8_BYTE_LEN[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4};

    static inline constexpr short OneCharLen(const char *src) noexcept {
        return UTF8_BYTE_LEN[(*((const unsigned char *) src)) >> 4];
    }

    extern size_t UTF8CharCounts(string_view str) noexcept;

    static inline size_t UTF8CharCounts(const char *s, size_t len) noexcept {
        return UTF8CharCounts(string_view(s, len));
    }

    extern Unicode UTF8Decode(string_view input);

    extern Unicode UTF8Decode(const char *s, size_t len);

    extern String UTF8Encode(unicode_view input);

    extern String UTF8Encode(const uint32_t *s, size_t len);

    extern String UTF8Encode(const char32_t *s, size_t len);

    extern String UTF8DoLower(string_view input);

    extern String UTF8DoUpper(string_view input);

    extern bool UTF8IsDigit(string_view input);

    extern bool UTF8IsAlpha(string_view input);

    extern String AsciiDoLower(string_view sv);

    extern String AsciiDoUpper(string_view sv);

    static inline bool AsciiIsDigit(string_view input) noexcept {
        return std::all_of(input.begin(), input.end(), [](char c) { return c >= '0' && c <= '9'; });
    }

    static inline bool AsciiIsAlpha(string_view input) noexcept {
        return std::all_of(input.begin(), input.end(), [](char c) {
            return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
        });
    }

}  // namespace tbir::runtime
